from pyecharts.charts import Line, Bar, Kline
import pyecharts.options as opts
from pyecharts.globals import ThemeType
from pyecharts.components import Image
from pyecharts.options import ComponentTitleOpts
import pandas as pd
import numpy as np


def get_iter_num(name):
    '''用以识别给出的品种需要哪些合约'''
    if name in ['沪原油', '20号胶', '黄金', '白银', '铜', '锌', '铝', '铅', '镍', '锡', '液化石油气']:
        contracts = ['L']
    elif name == '沥青':
        contracts = date_checker_3()
    elif name == '螺纹钢' or name == '热卷':
        contracts = date_checker_2()
    else:
        contracts = date_checker_1()
    return contracts


# 判断合约方法
def date_checker_1():
    '''1， 5， 9合约类型'''
    cur_year = pd.datetime.now().year
    yearhead = str(cur_year)[2:]
    cur_month = pd.datetime.now().month
    if 1 <= cur_month < 5:
        c = ['{}05'.format(yearhead), '{}09'.format(yearhead), '{}01'.format(str(int(yearhead) + 1))]
    elif 5 <= cur_month < 9:
        c = ['{}09'.format(yearhead), '{}01'.format(str(int(yearhead) + 1)), '{}05'.format(str(int(yearhead) + 1))]
    elif 9 <= cur_month <= 12:
        c = ['{}01'.format(str(int(yearhead) + 1)), '{}05'.format(str(int(yearhead) + 1)),
             '{}09'.format(str(int(yearhead) + 1))]
    return c


def date_checker_2():
    '''1， 5， 10合约类型'''
    cur_year = pd.datetime.now().year
    yearhead = str(cur_year)[2:]
    cur_month = pd.datetime.now().month
    if 1 <= cur_month < 5:
        c = ['{}05'.format(yearhead), '{}10'.format(yearhead), '{}01'.format(str(int(yearhead) + 1))]
    elif 5 <= cur_month < 10:
        c = ['{}10'.format(yearhead), '{}01'.format(str(int(yearhead) + 1)), '{}05'.format(str(int(yearhead) + 1))]
    elif 10 <= cur_month <= 12:
        c = ['{}01'.format(str(int(yearhead) + 1)), '{}05'.format(str(int(yearhead) + 1)),
             '{}10'.format(str(int(yearhead) + 1))]
    return c


def date_checker_3():
    '''6， 12合约类型'''
    cur_year = pd.datetime.now().year
    yearhead = str(cur_year)[2:]
    cur_month = pd.datetime.now().month
    if 1 <= cur_month < 6:
        c = ['{}06'.format(yearhead), '{}12'.format(yearhead), '{}06'.format(str(int(yearhead) + 1))]
    elif 6 <= cur_month < 12:
        c = ['{}12'.format(yearhead), '{}06'.format(str(int(yearhead) + 1)), '{}12'.format(str(int(yearhead) + 1))]
    elif cur_month == 12:
        c = ['{}06'.format(str(int(yearhead) + 1)), '{}12'.format(str(int(yearhead) + 1)),
             '{}06'.format(str(int(yearhead) + 2))]
    return c



# 制图通用方法
def draw_k_line(xax, klist_dict, type=None, width='600px', height='280px'):
    '''xax为x轴列表，时间顺序，klist是k线数据列表，数据格式为[[open, close, low, high], [...]]'''
    if type == 1:
        kl = Kline(init_opts=opts.InitOpts(theme=ThemeType.ESSOS))
    elif type == 2:
        kl = Kline(init_opts=opts.InitOpts(theme=ThemeType.INFOGRAPHIC))
    elif type == 3:
        kl = Kline(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    elif type == 4:
        kl = Kline(init_opts=opts.InitOpts(theme=ThemeType.SHINE))
    elif type == 5:
        kl = Kline(init_opts=opts.InitOpts(theme=ThemeType.WESTEROS))
    else:
        kl = Kline()
    kl.add_xaxis(xax)
    for name, klist in klist_dict.items():
        kl.add_yaxis(name, klist)
    kl.set_global_opts(yaxis_opts=opts.AxisOpts(is_scale=True), toolbox_opts=opts.ToolboxOpts(),
                       datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),
                       tooltip_opts=opts.TooltipOpts(trigger='axis'))
    kl.width = width
    kl.height = height
    return kl

def draw_single_y(xax, ys, type=None, width='600px', height='280px'):
    '''xax为x轴列表，时间序列；ys是字典，字典格式为{名称：数据列表}, 单y轴：适用于主力连续图'''
    if type == 1:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.ESSOS))
    elif type == 2:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.INFOGRAPHIC))
    elif type == 3:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.WONDERLAND))
    elif type == 4:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.SHINE))
    elif type == 5:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    elif type == 6:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
    else:
        line = Line()
    line.add_xaxis(xax)
    for name, list in ys.items():
        line.add_yaxis(name, list)
    line.set_global_opts(yaxis_opts=opts.AxisOpts(is_scale=True), toolbox_opts=opts.ToolboxOpts(),
                         datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),
                         tooltip_opts=opts.TooltipOpts(trigger='axis'))
    line.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    line.width = width
    line.height = height

    return line

def draw_double_y(xax, ysa, ysb, type=None, width='600px', height='280px'):
    '''双y轴图，折线与bar线组合，适用于现货基差图、价差、比价图'''
    if type == 1:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.ESSOS))
    elif type == 2:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.INFOGRAPHIC))
    elif type == 3:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.WONDERLAND))
    elif type == 4:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.SHINE))
    elif type == 5:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    elif type == 6:
        line = Line(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
    else:
        line = Line()
    line.add_xaxis(xax)
    for k, v in ysa.items():
        line.add_yaxis(k, v)
    line.set_global_opts(yaxis_opts=opts.AxisOpts(is_scale=True), toolbox_opts=opts.ToolboxOpts(),
                         datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),
                         tooltip_opts=opts.TooltipOpts(trigger='axis'))
    line.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    line.extend_axis(yaxis=opts.AxisOpts(is_scale=True))

    bar = Bar()
    bar.add_xaxis(xax)
    for k, v in ysb.items():
        bar.add_yaxis(k, v, yaxis_index=1)
    bar.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    line.overlap(bar)
    line.width = width
    line.height = height

    return line

# 期货制图法


def draw_main(name, seri, x=None):
    '''主力连续图'''
    datelist = seri.index.to_list()
    price = seri.to_list()
    dict = {'{}主连'.format(name): price}
    line = draw_single_y(datelist, dict, x, width='900px', height='400px')
    return line


# def draw_fut_index(name, fut_index, ry):
#     ry.index = ry.index.map(lambda x: ''.join([x[0: 4], x[5: 7], x[8:]]))
#     df = pd.concat([fut_index, ry], axis=1, sort=False)
#     datelist = df.index.to_list()
#     close = df['close'].to_list()
#     vol = df['volume'].to_list()
#     oi = df['open_interest'].to_list()
#     ry = df['roll_yield'].to_list()
#     ry_mark = "{}-{}".format(df['near_by'].to_list()[-1], df['deferred'].to_list()[-1])
#
#     line = (
#         Line()
#         .add_xaxis(datelist)
#         .add_yaxis('{}收盘价'.format(name), close, linestyle_opts=opts.LineStyleOpts(width=4, color='rgb(54, 54, 54)'))
#         .extend_axis(yaxis=opts.AxisOpts(is_scale=True, is_show=False))
#         .extend_axis(yaxis=opts.AxisOpts(is_scale=True))
#         .add_yaxis('{}展期收益'.format(ry_mark), ry, yaxis_index=1,
#                    linestyle_opts=opts.LineStyleOpts(width=3, color='rgb(255, 215, 0)'))
#         .set_global_opts(yaxis_opts=opts.AxisOpts(is_scale=True), toolbox_opts=opts.ToolboxOpts(),
#                          datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),
#                          tooltip_opts=opts.TooltipOpts(trigger='axis'))
#         .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
#     )
#     line2 = (
#         Line()
#         .add_xaxis(datelist)
#         .add_yaxis('VOL', vol, yaxis_index=2, is_smooth=True,
#                    areastyle_opts=opts.AreaStyleOpts(color='rgb(175, 238, 238)'))
#         .add_yaxis("OI", oi, yaxis_index=2, is_smooth=True,
#                    areastyle_opts=opts.AreaStyleOpts(color='rgb(250, 235, 215)'))
#         .set_series_opts(label_opts=opts.LabelOpts(is_show=False), areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
#         .set_global_opts(xaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
#                                                   is_scale=True, boundary_gap=False))
#     )
#     line.overlap(line2)
#     line.width = '900px'
#     line.height = '400px'
#
#     return line


def draw_spec_idctr(name, spdrdx, fut_index, ry):
    '''单个品种的一致预期、以及指数的收盘价、展期收益率、持仓、交易量'''
    ry.index = ry.index.map(lambda x: ''.join([x[0: 4], x[5: 7], x[8:]]))
    df = pd.concat([fut_index, ry, spdrdx], axis=1, sort=False)
    df.sort_index(ascending=True, inplace=True)
    np.seterr(divide='ignore', invalid='ignore')
    close = df['close'].to_list()
    vol = df['volume'].to_list()
    volln = np.log(np.array(vol))
    oi = df['open_interest'].to_list()
    oiln = np.log(np.array(oi))
    try:
        ry = df['roll_yield'].to_list()
    except:
        ry = []
    else:
        pass
    try:
        ry_mark = "{}-{}".format(df['near_by'].to_list()[-1], df['deferred'].to_list()[-1])
    except:
        ry_mark = 'N/A'
    else:
        pass
    datelist = df.index.to_list()
    informed = df['informed'].to_list()
    uninformed = df['uninformed'].to_list()
    senti = np.multiply(np.array(informed).astype(np.float), np.array(uninformed).astype(np.float))
    sentilist = senti.tolist()
    a = [100] * len(sentilist)
    sentimentdexarry = np.multiply(np.array(a), np.array(senti))
    sentix = sentimentdexarry[np.logical_not(np.isnan(sentimentdexarry))]
    if len(sentix) != 0:
        sentiaver = float(np.nanmean(sentix))
        sentistd = float(np.nanstd(sentix))
        sentiupper = sentiaver + sentistd * 2
        sentilower = sentiaver - sentistd * 2
    else:
        sentiaver = 0
        sentiupper = 0
        sentilower = 0
    sentimentdex = sentimentdexarry.tolist()
    dexlist = np.array(df['lsdexlite'].to_list()).astype(np.float).tolist()
    if len(dexlist) < 5:
        dexlite_ema = []
    else:
        ni = 5  # 指数移动平均的周期
        weig = np.exp(np.linspace(0, 1, ni))
        weights = weig / np.sum(weig)
        dxlt_ema = np.convolve(weights, dexlist, mode='valid')
        b = [10] * len(dxlt_ema)
        dexlitee = np.multiply(np.array(dxlt_ema), np.array(b)).tolist()
        addr = [None] * (ni - 1)
        dexlite_ema = addr + dexlitee
    line1 = (
        Line()
        .add_xaxis(datelist)
        .add_yaxis('{}收盘价'.format(name), close, linestyle_opts=opts.LineStyleOpts(width=4, color='rgb(54, 54, 54)'))
        .extend_axis(yaxis=opts.AxisOpts(is_scale=True))
        .extend_axis(yaxis=opts.AxisOpts(is_scale=True, is_show=False))
        .extend_axis(yaxis=opts.AxisOpts(is_scale=True, is_show=False))
        .add_yaxis('{}展期收益率'.format(ry_mark), ry, yaxis_index=1,
                   linestyle_opts=opts.LineStyleOpts(width=3, color='rgb(0, 229, 238)'))
        .add_yaxis("{}一致性预期".format(name), sentimentdex, yaxis_index=2,
                   linestyle_opts=opts.LineStyleOpts(width=3, color='rgb(255, 215, 0)'),
                   is_connect_nones=True,
                   markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(name='预期均线', y=sentiaver),
                                                         opts.MarkLineItem(name='预期上线', y=sentiupper),
                                                         opts.MarkLineItem(name='预期下线', y=sentilower), ]))
        .add_yaxis("知情者情绪", informed, yaxis_index=2,
                   linestyle_opts=opts.LineStyleOpts(width=1, type_='dotted'),
                   is_connect_nones=True)
        .add_yaxis("非知情者情绪", uninformed, yaxis_index=2,
                   linestyle_opts=opts.LineStyleOpts(width=1, type_='dotted'),
                   is_connect_nones=True)
        .add_yaxis("L/SliteEMA5", dexlite_ema, yaxis_index=2,
                   linestyle_opts=opts.LineStyleOpts(width=1, type_='solid'))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
        .set_global_opts(yaxis_opts=opts.AxisOpts(is_scale=True), toolbox_opts=opts.ToolboxOpts(),
                         datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),
                         tooltip_opts=opts.TooltipOpts(trigger='axis'))
    )
    line2 = (
        Line()
        .add_xaxis(datelist)
        .add_yaxis('VOL', volln, is_smooth=True, yaxis_index=3,
                   areastyle_opts=opts.AreaStyleOpts(color='rgb(175, 238, 238)'))
        .add_yaxis("OI", oiln, is_smooth=True, yaxis_index=3,
                   areastyle_opts=opts.AreaStyleOpts(color='rgb(250, 235, 215)'))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False), areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
        .set_global_opts(xaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
                                                  is_scale=True, boundary_gap=False))
    )
    line1.overlap(line2)
    line1.width = '900px'
    line1.height = '400px'
    return line1


def draw_contract(name, df):
    '''单个合约的价格、持仓量、持仓量变化图'''
    df.fillna(0, inplace=True)
    datelist = df.index.to_list()
    price = [int(x) for x in df['close'].to_list()]
    informed = [int(x) for x in df['informed'].to_list()]
    uninformed = [int(x) for x in df['uninformed'].to_list()]
    vol = df['vol'].to_list()
    vol = [int(x) for x in vol]
    oi = df['oi'].to_list()
    oi = [int(x) for x in oi]
    np.seterr(divide='ignore', invalid='ignore', )

    volln = np.log(vol).tolist()
    oiln = np.log(oi).tolist()
    senti = np.multiply(np.array(informed), np.array(uninformed))
    sentilist = senti.tolist()
    a = [100] * len(sentilist)
    sentimentdexarry = np.multiply(np.array(a), np.array(senti))
    sentix = sentimentdexarry[np.logical_not(np.isnan(sentimentdexarry))]
    if len(sentix) != 0:
        sentiaver = float(np.nanmean(sentix))
        sentistd = float(np.nanstd(sentix))
        sentiupper = sentiaver + sentistd * 2
        sentilower = sentiaver - sentistd * 2
    else:
        sentiaver = 0
        sentiupper = 0
        sentilower = 0
    sentimentdex = sentimentdexarry.tolist()
    dexlist = df['lsdexlite'].to_list()
    if len(dexlist) < 5:
        dexlite_ema = []
    else:
        ni = 5  # 指数移动平均的周期
        weig = np.exp(np.linspace(0, 1, ni))
        weights = weig / np.sum(weig)
        dxlt_ema = np.convolve(weights, dexlist)[ni-1: -(ni-1)]
        b = [10] * len(dxlt_ema)
        dexlitee = np.multiply(np.array(dxlt_ema), np.array(b)).tolist()
        addr = [None] * (ni-1)
        dexlite_ema = addr + dexlitee
    line = (
        Line()
        .add_xaxis(datelist)
        .add_yaxis("{}收盘价".format(name), price, linestyle_opts=opts.LineStyleOpts(width=4, color='rgb(54, 54, 54)'))
        .extend_axis(yaxis=opts.AxisOpts(is_scale=True, is_show=False))
        .extend_axis(yaxis=opts.AxisOpts(is_scale=True))
        .add_yaxis("一致性预期", sentimentdex, yaxis_index=1,
                   linestyle_opts=opts.LineStyleOpts(width=3, color='rgb(255, 215, 0)'),
                   is_connect_nones=True,
                   markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(name='预期均线', type_='Ave', y=sentiaver),
                                                         opts.MarkLineItem(name='预期上线', type_='Upper', y=sentiupper),
                                                         opts.MarkLineItem(name='预期下线', type_='Lower', y=sentilower), ]))
        .add_yaxis("知情者情绪", informed, yaxis_index=1,
                   linestyle_opts=opts.LineStyleOpts(width=1, type_='dotted', color='rgb(255, 0, 0)'),
                   is_connect_nones=True)
        .add_yaxis("非知情者情绪", uninformed, yaxis_index=1,
                   linestyle_opts=opts.LineStyleOpts(width=1, type_='dotted', color='rgb(0, 100, 0)'),
                   is_connect_nones=True)
        .add_yaxis("L/SliteEMA5", dexlite_ema, yaxis_index=1,
                   linestyle_opts=opts.LineStyleOpts(width=2, color='rgb(99, 184, 255)'))
        .set_global_opts(yaxis_opts=opts.AxisOpts(is_scale=True), toolbox_opts=opts.ToolboxOpts(),
                         datazoom_opts=opts.DataZoomOpts(range_start=0, range_end=100),
                         tooltip_opts=opts.TooltipOpts(trigger='axis'))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False))
    )
    ar = (
        Line()
        .add_xaxis(datelist)
        .add_yaxis('VOL', volln, yaxis_index=2, is_smooth=True,
                   areastyle_opts=opts.AreaStyleOpts(color='rgb(175, 238, 238)'))
        .add_yaxis("OI", oiln, yaxis_index=2, is_smooth=True,
                   areastyle_opts=opts.AreaStyleOpts(color='rgb(250, 235, 215)'))
        .set_series_opts(label_opts=opts.LabelOpts(is_show=False), areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
        .set_global_opts(xaxis_opts=opts.AxisOpts(axistick_opts=opts.AxisTickOpts(is_align_with_label=True),
                                                  is_scale=True, boundary_gap=False))
    )
    line.overlap(ar)
    line.width = '900px'
    line.height = '400px'
    return line


def draw_spot_spd(name, df, x=None):
    '''现货价格、主连及基差图'''
    datelist = df.index.to_list()
    spot_price = df['spot'].to_list()
    main_price = df['main_price'].to_list()
    basis = df['basis'].to_list()
    price_dict = {'{}现货价格'.format(name): spot_price, '{}主连价格'.format(name): main_price}
    basis_dict = {'{}主力基差'.format(name): basis}
    line = draw_double_y(datelist, price_dict, basis_dict, x, width='900px', height='400px')
    return line


def draw_spot_spd_jd(name, df):
    '''因为鸡蛋现货数据需要做处理，所以单独做一个函数'''
    datelist = df.index.to_list()
    spot_price = [x*500 for x in df['spot'].to_list()]
    main_price = df['main_price'].to_list()
    basis = df['basis'].to_list()
    price_dict = {'{}现货价格'.format(name): spot_price, '{}主连价格'.format(name): main_price}
    basis_dict = {'{}主力基差'.format(name): basis}
    line = draw_double_y(datelist, price_dict, basis_dict, width='900px', height='400px')
    return line


def draw_spot_spd_fg(name, df):
    '''因为玻璃现货数据需要做处理，所以单独做一个函数'''
    datelist = df.index.to_list()
    spot_price = [x*80 for x in df['spot'].to_list()]
    main_price = df['main_price'].to_list()
    basis = df['basis'].to_list()
    price_dict = {'{}现货价格'.format(name): spot_price, '{}主连价格'.format(name): main_price}
    basis_dict = {'{}主力基差'.format(name): basis}
    line = draw_double_y(datelist, price_dict, basis_dict, width='900px', height='400px')
    return line


def draw_future_curve(spotdf, fdf1, fdf2, fdf3):
    '''作单个品种的当天、前一天、上周、上两周、上月的远期曲线'''
    # 为了确保时间选择万无一失，使用期货主力的时间数据，并转换为现货时间数据，再去分别取值
    dlist_s = spotdf.index.to_list()
    dlist_f = fdf2.index.to_list()

    def check_list(dlist_s, dlist_f):
        if len(dlist_s) != 0 and len(dlist_f) != 0 and ''.join(dlist_s[-1].split('-')) == dlist_f[-1]:
            return dlist_s
        elif len(dlist_s) == 0 and len(dlist_f) != 0:
            return dlist_f
        elif len(dlist_f) == 0 and len(dlist_s) != 0:
            return dlist_s
        elif len(dlist_s) != 0 and len(dlist_f) != 0 and ''.join(dlist_s[-1].split('-')) != dlist_f[-1]:
            return dlist_f

    def get_date(dl, x):
        if len(dl[-1]) == 10:
            try:
                s_date = dl[x]
            except:
                f_date = None
                s_date = None
            else:
                f_date = ''.join(s_date.split('-'))
            return [f_date, s_date]
        elif len(dl[-1]) == 8:
            try:
                f_date = dl[x]
            except:
                f_date = None
                s_date = None
            else:
                s_date = '-'.join([f_date[:4], f_date[4:6], f_date[6:]])
            return [f_date, s_date]

    datelist = check_list(dlist_s, dlist_f)

    list1 = get_date(datelist, -1)
    list2 = get_date(datelist, -2)
    list3 = get_date(datelist, -6)
    list4 = get_date(datelist, -11)
    list5 = get_date(datelist, -21)

    def try_loc(df, x, y):
        try:
            outcome = df.loc[x, y]
        except:
            outcome = None
        else:
            pass
        return outcome

    x_axis = ['{}现货价格'.format(try_loc(spotdf, list1[1], 'name')), try_loc(fdf1, list1[0], 'ts_code'),
              try_loc(fdf2, list1[0], 'ts_code'), try_loc(fdf3, list1[0], 'ts_code')]
    curve1 = [try_loc(spotdf, list1[1], 'spot'), try_loc(fdf1, list1[0], 'close'),
              try_loc(fdf2, list1[0], 'close'), try_loc(fdf3, list1[0], 'close')]
    curve2 = [try_loc(spotdf, list2[1], 'spot'), try_loc(fdf1, list2[0], 'close'),
              try_loc(fdf2, list2[0], 'close'), try_loc(fdf3, list2[0], 'close')]
    curve3 = [try_loc(spotdf, list3[1], 'spot'), try_loc(fdf1, list3[0], 'close'),
              try_loc(fdf2, list3[0], 'close'), try_loc(fdf3, list3[0], 'close')]
    curve4 = [try_loc(spotdf, list4[1], 'spot'), try_loc(fdf1, list4[0], 'close'),
              try_loc(fdf2, list4[0], 'close'), try_loc(fdf3, list4[0], 'close')]
    curve5 = [try_loc(spotdf, list5[1], 'spot'), try_loc(fdf1, list5[0], 'close'),
              try_loc(fdf2, list5[0], 'close'), try_loc(fdf3, list5[0], 'close')]
    curve_dict = {
        list1[1]: curve1,
        list2[1]: curve2,
        list3[1]: curve3,
        list4[1]: curve4,
        list5[1]: curve5
    }
    line = draw_single_y(x_axis, curve_dict, type=2, width='900px', height='400px')
    return line


def draw_future_curve_fg(spotdf, fdf1, fdf2, fdf3):
    '''作单个品种的当天、前一天、上周、上两周、上月的远期曲线'''
    # 为了确保时间选择万无一失，使用期货主力的时间数据，并转换为现货时间数据，再去分别取值
    dlist_s = spotdf.index.to_list()
    dlist_f = fdf2.index.to_list()

    def check_list(dlist_s, dlist_f):
        if len(dlist_s) != 0 and len(dlist_f) != 0 and ''.join(dlist_s[-1].split('-')) == dlist_f[-1]:
            return dlist_s
        elif len(dlist_s) == 0 and len(dlist_f) != 0:
            return dlist_f
        elif len(dlist_f) == 0 and len(dlist_s) != 0:
            return dlist_s
        elif len(dlist_s) != 0 and len(dlist_f) != 0 and ''.join(dlist_s[-1].split('-')) != dlist_f[-1]:
            return dlist_f

    def get_date(dl, x):
        if len(dl[-1]) == 10:
            try:
                s_date = dl[x]
            except:
                f_date = None
                s_date = None
            else:
                f_date = ''.join(s_date.split('-'))
            return [f_date, s_date]
        elif len(dl[-1]) == 8:
            try:
                f_date = dl[x]
            except:
                f_date = None
                s_date = None
            else:
                s_date = '-'.join([f_date[:4], f_date[4:6], f_date[6:]])
            return [f_date, s_date]

    datelist = check_list(dlist_s, dlist_f)

    list1 = get_date(datelist, -1)
    list2 = get_date(datelist, -2)
    list3 = get_date(datelist, -6)
    list4 = get_date(datelist, -11)
    list5 = get_date(datelist, -21)

    def try_loc(df, x, y):
        try:
            outcome = df.loc[x, y]
        except:
            outcome = None
        else:
            pass
        return outcome

    def try_loc_2(df, x, y):
        try:
            outcome = df.loc[x, y]
        except:
            outcome = None
        else:
            outcome *= 80
        return outcome

    x_axis = ['{}现货价格'.format(try_loc(spotdf, list1[1], 'name')), try_loc(fdf1, list1[0], 'ts_code'),
              try_loc(fdf2, list1[0], 'ts_code'), try_loc(fdf3, list1[0], 'ts_code')]
    curve1 = [try_loc_2(spotdf, list1[1], 'spot'), try_loc(fdf1, list1[0], 'close'),
              try_loc(fdf2, list1[0], 'close'), try_loc(fdf3, list1[0], 'close')]
    curve2 = [try_loc_2(spotdf, list2[1], 'spot'), try_loc(fdf1, list2[0], 'close'),
              try_loc(fdf2, list2[0], 'close'), try_loc(fdf3, list2[0], 'close')]
    curve3 = [try_loc_2(spotdf, list3[1], 'spot'), try_loc(fdf1, list3[0], 'close'),
              try_loc(fdf2, list3[0], 'close'), try_loc(fdf3, list3[0], 'close')]
    curve4 = [try_loc_2(spotdf, list4[1], 'spot'), try_loc(fdf1, list4[0], 'close'),
              try_loc(fdf2, list4[0], 'close'), try_loc(fdf3, list4[0], 'close')]
    curve5 = [try_loc_2(spotdf, list5[1], 'spot'), try_loc(fdf1, list5[0], 'close'),
              try_loc(fdf2, list5[0], 'close'), try_loc(fdf3, list5[0], 'close')]
    curve_dict = {
        list1[1]: curve1,
        list2[1]: curve2,
        list3[1]: curve3,
        list4[1]: curve4,
        list5[1]: curve5
    }
    line = draw_single_y(x_axis, curve_dict, type=2, width='900px', height='400px')
    return line


def draw_future_curve_jd(spotdf, fdf1, fdf2, fdf3):
    '''作单个品种的当天、前一天、上周、上两周、上月的远期曲线'''
    # 为了确保时间选择万无一失，使用期货主力的时间数据，并转换为现货时间数据，再去分别取值
    dlist_s = spotdf.index.to_list()
    dlist_f = fdf2.index.to_list()

    def check_list(dlist_s, dlist_f):
        if len(dlist_s) != 0 and len(dlist_f) != 0 and ''.join(dlist_s[-1].split('-')) == dlist_f[-1]:
            return dlist_s
        elif len(dlist_s) == 0 and len(dlist_f) != 0:
            return dlist_f
        elif len(dlist_f) == 0 and len(dlist_s) != 0:
            return dlist_s
        elif len(dlist_s) != 0 and len(dlist_f) != 0 and ''.join(dlist_s[-1].split('-')) != dlist_f[-1]:
            return dlist_f

    def get_date(dl, x):
        if len(dl[-1]) == 10:
            try:
                s_date = dl[x]
            except:
                f_date = None
                s_date = None
            else:
                f_date = ''.join(s_date.split('-'))
            return [f_date, s_date]
        elif len(dl[-1]) == 8:
            try:
                f_date = dl[x]
            except:
                f_date = None
                s_date = None
            else:
                s_date = '-'.join([f_date[:4], f_date[4:6], f_date[6:]])
            return [f_date, s_date]

    datelist = check_list(dlist_s, dlist_f)

    list1 = get_date(datelist, -1)
    list2 = get_date(datelist, -2)
    list3 = get_date(datelist, -6)
    list4 = get_date(datelist, -11)
    list5 = get_date(datelist, -21)

    def try_loc(df, x, y):
        try:
            outcome = df.loc[x, y]
        except:
            outcome = None
        else:
            pass
        return outcome

    def try_loc_2(df, x, y):
        try:
            outcome = df.loc[x, y]
        except:
            outcome = None
        else:
            outcome *= 500
        return outcome

    x_axis = ['{}现货价格'.format(try_loc(spotdf, list1[1], 'name')), try_loc(fdf1, list1[0], 'ts_code'),
              try_loc(fdf2, list1[0], 'ts_code'), try_loc(fdf3, list1[0], 'ts_code')]
    curve1 = [try_loc_2(spotdf, list1[1], 'spot'), try_loc(fdf1, list1[0], 'close'),
              try_loc(fdf2, list1[0], 'close'), try_loc(fdf3, list1[0], 'close')]
    curve2 = [try_loc_2(spotdf, list2[1], 'spot'), try_loc(fdf1, list2[0], 'close'),
              try_loc(fdf2, list2[0], 'close'), try_loc(fdf3, list2[0], 'close')]
    curve3 = [try_loc_2(spotdf, list3[1], 'spot'), try_loc(fdf1, list3[0], 'close'),
              try_loc(fdf2, list3[0], 'close'), try_loc(fdf3, list3[0], 'close')]
    curve4 = [try_loc_2(spotdf, list4[1], 'spot'), try_loc(fdf1, list4[0], 'close'),
              try_loc(fdf2, list4[0], 'close'), try_loc(fdf3, list4[0], 'close')]
    curve5 = [try_loc_2(spotdf, list5[1], 'spot'), try_loc(fdf1, list5[0], 'close'),
              try_loc(fdf2, list5[0], 'close'), try_loc(fdf3, list5[0], 'close')]
    curve_dict = {
        list1[1]: curve1,
        list2[1]: curve2,
        list3[1]: curve3,
        list4[1]: curve4,
        list5[1]: curve5
    }
    line = draw_single_y(x_axis, curve_dict, type=2, width='900px', height='400px')
    return line


def draw_separator(name):
    image = Image()

    img_src = (
        "C://Users//Daniel//Documents//ProjectStarGaze//dataprocessor//"
        "separator.jpg"
    )
    image.add(
        src=img_src,
        style_opts={"width": "1800px", "height": "50px"},
    ).set_global_opts(
        title_opts=ComponentTitleOpts(title="{}数据区".format(name))
    )
    return image


def draw_spd(namea, sera, nameb, serb, x=None):
    '''作两合约价格及合约间月差专用，因为涉及到不同的时间尺度'''
    # sera为近期合约的收盘价Series, serb是相对远期合约的Series
    datelist = sera.index.to_list()

    spd = (sera - serb).to_list()
    p_list_b = []
    for date in datelist:
        try:
            p = serb[date]
        except:
            p = None
        else:
            pass
        p_list_b.append(p)
    p_list_a = sera.to_list()
    dict_p = {namea: p_list_a,
              nameb: p_list_b}
    dict_spd = {'spd': spd}
    line = draw_double_y(datelist, dict_p, dict_spd, x, width='900px', height='400px')
    return line


def draw_price_ratio(namea, sera, nameb, serb, x=None):
    '''作不同品种之间的比价图'''
    datelist = (sera + serb).index.to_list()
    price_a, price_b = [], []
    for date in datelist:
        try:
            pa = sera[date]
        except:
            pa = None
        else:
            pass
        price_a.append(pa)

        try:
            pb = serb[date]
        except:
            pb = None
        else:
            pass
        price_b.append(pb)
    ratio = (sera / serb).to_list()
    s_a = pd.Series(price_a)
    s_b = pd.Series(price_b)
    corr = round(s_a.corr(s_b), 2)
    dict_p = {namea: price_a,
              nameb: price_b}
    dict_r = {'{}/{}比价|相关性：{}'.format(namea, nameb, corr): ratio}

    line = draw_double_y(datelist, dict_p, dict_r, x)
    return line


def draw_price_dif(namea, sera, nameb, serb, x=None):
    '''作不同品种之间的价差图'''
    datelist = (sera + serb).index.to_list()
    price_a, price_b = [], []
    for date in datelist:
        try:
            pa = sera[date]
        except:
            pa = None
        else:
            pass
        price_a.append(pa)

        try:
            pb = serb[date]
        except:
            pb = None
        else:
            pass
        price_b.append(pb)
    dif = (sera - serb).to_list()
    s_a = pd.Series(price_a)
    s_b = pd.Series(price_b)
    corr = round(s_a.corr(s_b), 2)
    dict_p = {namea: price_a,
              nameb: price_b}
    dict_d = {'{}-{}价差|相关性：{}'.format(namea, nameb, corr): dif}

    line = draw_double_y(datelist, dict_p, dict_d, x)
    return line


def draw_cus_dif(namea, sera, nameb, serb, x, y, t=None):
    '''作两个不同品种之间自定比例的价差图'''
    datelist = (sera + serb).index.to_list()
    price_a, price_b = [], []
    for date in datelist:
        try:
            pa = sera[date]
        except:
            pa = None
        else:
            pass
        price_a.append(pa)

        try:
            pb = serb[date]
        except:
            pb = None
        else:
            pass
        price_b.append(pb)
    dif = ((sera*x) - (serb*y)).to_list()
    s_a = pd.Series(price_a)
    s_b = pd.Series(price_b)
    corr = round(s_a.corr(s_b), 2)
    dict_p = {namea: price_a,
              nameb: price_b}
    dict_d = {'{}{}-{}{}价差|相关性：{}'.format(x, namea, y, nameb, corr): dif}
    line = draw_double_y(datelist, dict_p, dict_d, t)
    return line


def arbi_record(na, seria, nb, serib, x=1, y=1, opt=1, cat=1):
    '''记录期货指数的品种间比价/价差历史水平'''
    if cat == 1:
        # category 1: future index; category 2: spot price
        catname = "Index"
    elif cat == 2:
        catname = "Spot"
    seria.name = 'aprice'
    serib.name = 'bprice'
    df = pd.concat([seria, serib], axis=1, sort=False)
    df.dropna(axis=0, how='any', inplace=True)
    a = df['aprice']
    b = df['bprice']
    corr = round(a.corr(b), 2)
    np.seterr(divide='ignore', invalid='ignore')
    if opt == 1:
        # 1是比价， 2是价差
        ratio = (a / b).to_list()
        if len(np.array(ratio)[np.logical_not(np.isnan(np.array(ratio)))]) >= 120 and pd.isna(ratio[-1]) is False:
            clean_ratio = np.array(ratio)[np.logical_not(np.isnan(np.array(ratio)))].tolist()
            cur_ratio = ratio[-1]
            cal_list = np.array(ratio)[np.array(ratio) <= cur_ratio].tolist()
            cur_pos = round(((len(cal_list) / len(clean_ratio)) * 100), 2)
            cur_value = round(cur_ratio, 2)
            if cur_pos >= 85:
                with open('ratioup.csv', mode='a+', encoding='gbk') as f:
                    f.write('{}: {}{}/{}{},{},{},{}\n'.format(catname, x, na, y, nb, cur_value, cur_pos, corr))
            elif cur_pos <= 15:
                with open('ratiodown.csv', mode='a+', encoding='gbk') as f:
                    f.write('{}: {}{}/{}{},{},{},{}\n'.format(catname, x, na, y, nb, cur_value, cur_pos, corr))
    elif opt == 2:
        dif = ((a*x) - (y*b)).to_list()
        if len(np.array(dif)[np.logical_not(np.isnan(np.array(dif)))]) >= 120 and pd.isna(dif[-1]) is False:
            clean_dif = np.array(dif)[np.logical_not(np.isnan(np.array(dif)))].tolist()
            cur_dif = dif[-1]
            cal_list = np.array(dif)[np.array(dif) <= cur_dif].tolist()
            cur_pos = round(((len(cal_list) / len(clean_dif)) * 100), 2)
            cur_value = round(cur_dif, 2)
            if cur_pos >= 85:
                with open('difup.csv', mode='a+', encoding='gbk') as f:
                    f.write('{}: {}{}-{}{},{},{},{}\n'.format(catname, x, na, y, nb, cur_value, cur_pos, corr))
            elif cur_pos <= 15:
                with open('difdown.csv', mode='a+', encoding='gbk') as f:
                    f.write('{}: {}{}-{}{},{},{},{}\n'.format(catname, x, na, y, nb, cur_value, cur_pos, corr))


def draw_index_k(name, df, x):
    '''做指数K线,数据格式为[[open, close, low, high], [...]]'''
    datelist = df.index.to_list()
    k_data = []
    for d in datelist:
        d_open = df['open'][d]
        d_close = df['close'][d]
        d_low = df['low'][d]
        d_high = df['close'][d]
        single_d = [d_open, d_close, d_low, d_high]
        k_data.append(single_d)
    k_data_dict = {name: k_data}
    kl = draw_k_line(datelist, k_data_dict, x)
    return kl

